#include "CommandHandler.h"

#include "MultimodalTestApp.h"

#include "VoiceRecognizer.h"
#include "Speaker.h"
#include "NetListener.h"
#include "Wiimote.h"

#include <Windows.h>

//The command handler is the "bridge" between modality receivers and the actual game. The attached threads to recognize
//motion (Wii), touch (mobile devices: Android) and voice commands (Microsoft Speech API) have a reference to the command handler
//and will continuously forward their captured and recognized user actions to this object. The Ogre game will then regularly
//read the current values from the command handler. The reason for this approach is first of all the clear separation and modular
//design. Secondly, no cross-threading issues are encountered when following this method.

//Define the threads for the different input modalities
DWORD WINAPI NetListenerThread(LPVOID lpParameter); //DO NOT MOVE those declarations outside the CPP! Will not work!
DWORD WINAPI VoiceRecognizerThread(LPVOID lpParameter);
DWORD WINAPI WiimoteThread(LPVOID lpParameter);


//Constructor
	CommandHandler::CommandHandler(MultimodalTestApp *app){

		//Set world reference
	m_world = app->getWorld();
	speaker = new Speaker();//Create a speaker to issue voice commands
	
	//Initialize default game values
	actionFromListener=NONE;
	gameStateFromListener=RUNNING;
	physicsElementFromListener[GRAVITY]=12;
	physicsElementFromListener[FRICTION]=0.95;
	physicsElementFromListener[BOUNCE]=0.83;
	actionFromApp=NONE;
	gameStateFromApp=NONE;

	//According to the game parameters, start the appropriate threads
	if(useVoiceRecognizer)
		startVoiceRecognizer();
	if(useNetListener)
		startNetListener();
	if(useWiimote)
		startWiiRemote();
	if(!startAppDirectly)
		//If the game is not started directly, then the main thread must sleep such that the just created threads do not exit immediately but can be tested and will continuously listen to user input.
		Sleep(99999);

	//if(useVoiceRecognizer)
	//WaitForSingleObject(voiceRecognizerHandle, INFINITE); // wait for thread to exit
	//if(useNetListener)
	//WaitForSingleObject(netListenerHandle, INFINITE); // wait for thread to exit
}
	//The destructor
CommandHandler::~CommandHandler(void){}

	//Activate the listener to get commands over the internet protocol
void CommandHandler::startNetListener(void){
	DWORD netListenerId;
	netListener = new NetListener(this);

	HANDLE netListenerHandle = CreateThread( NULL, 0, NetListenerThread, this, 0L, &netListenerId);
	//netListenerHandle = CreateThread( NULL, 0, NetListenerThread, this, 0L, &netListenerId);

	//if(!startAppDirectly && !useVoiceRecognizer)
	//WaitForSingleObject(netListenerHandle, INFINITE); // wait for thread to exit
}

	//Activate the listener to get commands captured by the voice recognizer
void CommandHandler::startVoiceRecognizer(void){
	DWORD voiceRecognizerId;
	voiceRecognizer = new VoiceRecognizer(this);

	HANDLE voiceRecognizerHandle= CreateThread( NULL, 0, VoiceRecognizerThread, this, 0L, &voiceRecognizerId);
	//voiceRecognizerHandle= CreateThread( NULL, 0, VoiceRecognizerThread, this, 0L, &voiceRecognizerId);
	//Do not use this --> //WaitForSingleObject(voiceRecognizerHandle, INFINITE); // wait for thread to exit

	//if(!startAppDirectly && !useNetListener)
	//WaitForSingleObject(voiceRecognizerHandle, INFINITE); // wait for thread to exit
}

	//Adjusting game state (e.g. pausing the game etc.)
void CommandHandler::setGameState(bool fromApp, int gameState){
	if(fromApp)
		this->gameStateFromApp=gameState;
	else{
		if(this->gameStateFromApp==PAUSE && gameState==PAUSE)
		this->gameStateFromListener=RESUME;
		else
			this->gameStateFromListener=gameState;
	}
}

//Getting game state (e.g. pausing the game etc.)
int CommandHandler::getGameState(bool fromApp){
	if(fromApp)
	return gameStateFromApp;
	else
	return gameStateFromListener;
}

//Adjusting action (e.g. grabbing etc.)
void CommandHandler::setAction(bool fromApp, int action){
	if(fromApp)
	this->actionFromApp=action;
	else
	this->actionFromListener=action;
}

//Getting action (e.g. grabbing etc.)
int CommandHandler::getAction(bool fromApp){
	if(fromApp)
		return actionFromApp;
	else
		return actionFromListener;
}

//Adjusting physic values (e.g. gravity etc.)
void CommandHandler::setPhysics(bool fromApp, int physicsElement, float physicsValue)
{
	if(fromApp)
		;//N/A
	else{
		physicsElementFromListener[physicsElement]=physicsValue;
	}
}

//Getting physic values (e.g. gravity etc.)
float CommandHandler::getPhysics(bool fromApp, int physicsElement)
{
	if(fromApp)
		;//N/A
	else
		return physicsElementFromListener[physicsElement];
}

//Adjusting hand position
void CommandHandler::setHandPosition(Ogre::Vector2 handPosition)
{
	app->setHandPosition(handPosition);
}

//Getting hand position
Ogre::Vector2 CommandHandler::getHandPosition(void)
{
	//wiiremote->isApressed;
	return Ogre::Vector2(wiiremote->Xposition,wiiremote->Yposition);
}

//Separately running thread listening to incoming network traffic
DWORD WINAPI NetListenerThread(LPVOID lpParameter)
{
	CommandHandler *commandHandler = (CommandHandler*) lpParameter;
    commandHandler->getNetListener()->startListening();
	return 0;
}

//Separately running thread listening for voice commands
DWORD WINAPI VoiceRecognizerThread(LPVOID lpParameter)
{
	CommandHandler *commandHandler = (CommandHandler*) lpParameter;
	commandHandler->getVoiceRecognizer()->listen(true);
	return 0;
}

//Activate the Wii thread to get commands captured by Wiimote
void CommandHandler::startWiiRemote(void){
	DWORD wiimoteId;
	wiiremote =new wiimote(this);
	HANDLE wiimoteHandle = CreateThread( NULL, 0, WiimoteThread, this, 0L, &wiimoteId);
}

//Separately running thread listening for Wii movements
DWORD WINAPI WiimoteThread(LPVOID lpParameter)
{
	CommandHandler *commandHandler = (CommandHandler*) lpParameter;
    commandHandler->getWiiRemote()->startWiiRemote();
	return 0;
}